home *** CD-ROM | disk | FTP | other *** search
- #include <stdlib.h>
- #include <stdio.h>
- #include "TDCS.h"
-
- /*
- * =================================================================
- * statistical encoder
- * =================================================================
- */
- void cremate(void) {
- }
-
- /*
- * =================================================================
- * lz77 preprocessor
- * =================================================================
- */
-
- void ArrayClear(register struct hashroot *Array __asm__("a0")) {
- bzero(Array, LOOKUP_SIZE * sizeof(struct hashroot));
- }
-
- int annihilate(register int inSize __asm__ ("d0"),
- register unsigned char *inMem __asm__ ("a0"),
- register int outSize __asm__ ("d1"),
- register unsigned char *outMem __asm__ ("a1"),
- int Mode) {
- register unsigned char *pasteMem;
- #define parseMem inMem
- register struct hashroot *Array;
- struct ExecBase *SysBase;
- int indexPos;
- unsigned int index;
- unsigned int *indexMem;
- void *memPool;
-
- if(!(Array = malloc(LOOKUP_SIZE * sizeof(struct hashroot))))
- return ERROR_LESSMEM;
-
- ArrayClear(Array);
-
- pasteMem = outMem;
- outSize = inSize; /* do not grow size */
- outMem += outSize; /* last valid output */
-
- indexMem = ((unsigned int *)pasteMem)++; /* store the inde before each block */
- index = 0;
- indexPos = INDEX_LENGTH - 1;
-
- while (inSize > 0) {
- unsigned short int oldMatch = MIN_MATCH - 1;
- int oldOffset;
-
- /*
- * =================================================================
- * Hashes
- * =================================================================
- */
- #define StoreHash() ({ \
- register struct hashroot *root; \
- register int maxcnt; \
- \
- root = &Array[LOOKUP_PREFUNCTION(parseMem)]; \
- if((maxcnt = root->maxcount)) { /* begin with 500k + 500k */ \
- register int count, add; \
- register struct hashnode *node; \
- \
- add = 0; \
- node = root->node; \
- count = node->count; \
- node->entries[count++] = parseMem; /* register actual match */ \
- \
- if(count > MAX_MATCH) { \
- if((node->entries[count - 1] - node->entries[count - 1 - MAX_MATCH - 1]) == (MAX_MATCH + 1)) { \
- count--; \
- bcopy(&node->entries[count - MAX_MATCH], &node->entries[count - MAX_MATCH - 1], MAX_MATCH * sizeof(unsigned char *)); \
- } \
- } \
- \
- if(count >= maxcnt) { /* expand it */ \
- if(maxcnt < NODES_CLUSTER) \
- add = maxcnt; /* double size */ \
- else \
- add = NODES_CLUSTER; \
- } \
- else if((count > 1) && (count <= (maxcnt >> 1))) { /* reduce it */ \
- if(maxcnt > NODES_CLUSTER) \
- add = -(NODES_CLUSTER); \
- else if((maxcnt >>= 1) < NODES_MIN) /* half size */ \
- add = -(maxcnt - NODES_MIN); \
- } \
- \
- if(add) { \
- maxcnt += add; \
- if(!(node = malloc(NODES_SIZE(maxcnt)))) \ \
- return ERROR_LESSMEM; \
- bcopy(root->node, node, NODES_SIZE(count - NODES_BACKWALL)); \
- free(root->node, NODES_SIZE(root->maxcount)); \
- \
- root->node = node; \
- root->maxcount = maxcnt; \
- } \
- node->count = count; \
- } \
- else { \
- register struct hashnode *node; \
- \
- if(!(node = root->node = malloc(NODES_SIZE(NODES_MIN)))) \
- return ERROR_LESSMEM; \
- root->maxcount = NODES_MIN; \
- node->count = 1; \
- node->entries[0] = parseMem; /* register actual match */ \
- } \
- })
-
- /*
- * =================================================================
- * Matches
- * =================================================================
- */
- #define FindMatch() ({ \
- while (--tries >= 0) { \
- register unsigned char *beginHist = *--tryhistory; /* characters after first character */ \
- \
- if (*((unsigned short int *)(beginHist + oldMatch - 1)) == \
- *((unsigned short int *)(parseMem + oldMatch - 1))) { /* compare with last character */ \
- if (*((unsigned short int *)(beginHist + 1)) == /* already verified from hash */ \
- *((unsigned short int *)(parseMem + 1))) { \
- /* do not invalidate flowing beginHist and constant beginPars */ \
- register unsigned char *newHist = beginHist + MIN_MATCH; \
- register unsigned char *newPars = parseMem + MIN_MATCH; \
- register int newMatch = MIN_MATCH + 3; /* first byte allready parsed */ \
- /* hopefully execute from left to right */ \
- while (newMatch < (MAX_MATCH + 3)) { /* do not overflow */ \
- if (*((unsigned int *)newHist)++ != \
- *((unsigned int *)newPars)++) { /* compare with characters after first character */ \
- break; \
- } \
- newMatch += 4; \
- } \
- if(newMatch > oldMatch) { \
- newHist -= 4; \
- newPars -= 4; \
- if (*((unsigned short int *)newHist)++ != \
- *((unsigned short int *)newPars)++) { /* compare with characters after first character */ \
- newMatch -= 2; \
- newHist -= 2; \
- newPars -= 2; \
- } \
- if (*((unsigned char *)(newHist)) != \
- *((unsigned char *)(newPars))) { /* compare with characters after first character */ \
- newMatch -= 1; \
- } \
- \
- if (newMatch > oldMatch) { /* accept if longer than last match */ \
- oldOffset = newHist - newPars; /* calculate negative offset */ \
- if ((oldMatch = newMatch) >= MAX_MATCH) { /* correct length if longer than maximal match */ \
- oldMatch = MAX_MATCH; \
- break; /* do not continue if maximum matchlength reached */ \
- } \
- } \
- } \
- } \
- } \
- } \
- })
-
- #define GetHash() ({ \
- register struct hashnode *node; \
- register int remove; \
- \
- if(!(node = Array[remove = LOOKUP_PREFUNCTION(parseMem)].node)) { \
- if(!(node = Array[remove].node = malloc(NODES_SIZE(NODES_MIN)))) \
- return ERROR_LESSMEM; \
- Array[remove].maxcount = NODES_MIN; \
- node->count = 0; \
- } \
- else { \
- register int tries; \
- register unsigned char **tryhistory; \
- \
- tries = node->count; \
- \
- for(remove = 0; tries > remove; remove++) { /* while the history-entries are too big, remove them, thats okay, they are distance-sorted */ \
- if((parseMem - node->entries[remove]) <= (HISTORY_LENGTH)) \
- break; \
- } \
- \
- if(remove) { /* streight move the entries from right to left to prevent sorting order */ \
- tries -= remove; \
- bcopy(&node->entries[remove], &node->entries[0], tries * sizeof(unsigned char *)); \
- node->count = tries; \
- } \
- tryhistory = &node->entries[tries]; \
- FindMatch(); \
- } \
- })
-
- #define GetMatch() ({ \
- GetHash(); \
- })
-
- #define UpdateIndex() ({ \
- if (--indexPos < 0) { /* flush index if full */ \
- *indexMem = index; \
- indexMem = ((unsigned int *)pasteMem)++; \
- index = 0; \
- indexPos = INDEX_LENGTH - 1; \
- } \
- \
- if (pasteMem > outMem) /* brute break if destination overflow, TODO: clean break, not abort() */ \
- return ERROR_OVERFLOW; \
- })
-
- #define StoreLiteral() ({ \
- StoreHash(); \
- \
- /* store 8bit literal */ \
- *pasteMem++ = *parseMem++; /* store plain literal */ \
- inSize -= sizeof(unsigned char); /* reduce number of left bytes */ \
- \
- UpdateIndex(); \
- })
-
- #define StoreMatch() ({ \
- register int setMatch; \
- \
- if (oldMatch > (unsigned short int)inSize) /* protect against underflow */ \
- oldMatch = (unsigned short int)inSize; \
- if ((setMatch = oldMatch - MIN_MATCH) >= 0) { \
- register int orIndex; \
- \
- if ((setMatch <= 0x3) && (oldOffset >= 0xFFFFC000)) { \
- *((unsigned short int *)pasteMem)++ = (unsigned short int)((((unsigned short int)oldOffset) << 2) | (setMatch)); \
- orIndex = 0x1; \
- } \
- else if ((setMatch <= 0xF) && (oldOffset >= 0xFFFFF000)) { \
- *((unsigned short int *)pasteMem)++ = (unsigned short int)((((unsigned short int)oldOffset) << 4) | (setMatch)); \
- orIndex = 0x2; \
- } \
- else { \
- /* store 16bit history */ \
- *((unsigned short int *)pasteMem)++ = (unsigned short int)(oldOffset); \
- /* store 8bit length */ \
- *pasteMem++ = (unsigned char)(setMatch); \
- orIndex = 0x3; \
- } \
- \
- index |= (orIndex << (indexPos * INDEX_BITS)); \
- } \
- else { \
- /* store 8bit literal */ \
- *pasteMem++ = *parseMem; /* store plain literal */ \
- oldMatch = sizeof(unsigned char); \
- } \
- \
- inSize -= oldMatch; /* reduce number of left bytes */ \
- /* goto position after valid match */ \
- for((short int)oldMatch -= 1; (short int)oldMatch >= 0; (short int)oldMatch--) { /* runs oldMatch - 1 times */ \
- StoreHash(); \
- parseMem++; \
- } \
- \
- UpdateIndex(); \
- })
-
- /*
- * =================================================================
- * Main-Parsing
- * =================================================================
- */
- GetMatch(); /* set initial match */
- if (oldMatch < MAX_MATCH) { /* try only something better if there could be something longer */
- register unsigned short int k;
- register unsigned short int revMatch = oldMatch; /* store old state */
- register int revOffset = oldOffset;
-
- for (k = 1; k < Mode; k++) { /* we leave this loop only if none of the next two tries matches better */
- parseMem++; /* try next possible match */
- GetMatch();
-
- if ((oldMatch - k) > revMatch) { /* match is better, store everything before */
- revMatch = oldMatch; /* store new state */
- revOffset = oldOffset;
- parseMem -= k; /* jump to beginning of best-match-sliding */
- oldMatch = MIN_MATCH - 1; /* store them all as literals */
-
- for (; k >= 1; k--) /* store every previous try */
- StoreLiteral();
-
- if (revMatch >= MAX_MATCH) { /* brute break if match reaches maximum */
- k = 1; /* don't rewind parseMem if we break the loop */
- break;
- }
- }
- }
-
- parseMem -= (k - 1); /* none of the two tries matches better, so rewind both tries (means three bytes) */
- oldOffset = revOffset; /* restore old state */
- oldMatch = revMatch;
- }
- StoreMatch(); /* save last match */
- }
-
- index |= (0x3 << (indexPos * INDEX_BITS)); /* flush index */
- *indexMem = index; /* and store */
- *((unsigned short int *)pasteMem)++ = 0;
-
- outSize = pasteMem - (outMem - outSize); /* get size */
-
- return outSize;
- }
-